package SGEngine

import (
	"container/list"
	//"fmt"
	//"math"
	"time"
)

var (
	ACTimeUpdate timeUpdate
)

func init() {
	ACTimeUpdate.UpdateList = list.New()
}

type TUpdateFunc func(dt float64, this interface{})

type Updater struct {
	UpdateFunc    TUpdateFunc
	enable        bool
	del           bool
	This          interface{}
	updatetime    float64
	Addupdatetime float64
}

func (u *Updater) IsEnable() bool {
	return u.enable
}

func (u *Updater) SetEnable(state bool) {

}

func (u *Updater) Del() {
	u.del = true
}

type timeUpdate struct {
	UpdateList *list.List
	LastTime   float64
}

func (t *timeUpdate) AddUpdate(updatefunc TUpdateFunc) {
	t.AddUpdater(updatefunc, nil, 0)
}

func (t *timeUpdate) AddUpdateTime(updatefunc TUpdateFunc, uptime float64) *Updater {
	return t.AddUpdater(updatefunc, nil, uptime)
}

func (t *timeUpdate) AddUpdater(updatefunc TUpdateFunc, updater interface{}, uptime float64) *Updater {
	mUpdater := new(Updater)
	mUpdater.enable = true
	mUpdater.UpdateFunc = updatefunc
	mUpdater.This = updater
	mUpdater.updatetime = uptime
	t.UpdateList.PushBack(mUpdater)

	return mUpdater
}

func (t *timeUpdate) update() {
	CurTime := float64(time.Now().UnixNano()) * 0.000000001
	DelTime := CurTime - t.LastTime
	for e := t.UpdateList.Front(); e != nil; e = e.Next() {
		mUpdater := e.Value.(*Updater)
		if mUpdater.del == true {
			t.UpdateList.Remove(e)
		} else {

			if mUpdater.updatetime == 0 {
				mUpdater.UpdateFunc(DelTime, mUpdater.This)
			} else {
				if mUpdater.Addupdatetime > mUpdater.updatetime {
					mUpdater.UpdateFunc(DelTime, mUpdater.This)
					mUpdater.Addupdatetime = 0
				} else {
					mUpdater.Addupdatetime += DelTime
				}
			}
		}
	}

	t.LastTime = float64(time.Now().UnixNano()) * 0.000000001
}

////////////////////////////////////////////////////////////////////

type moveToS struct {
	NeedTime    float64
	curtime     float64
	node        INode
	Dis         *Vec3
	Dest        *Vec3
	MoveEndFunc func(INode)
	Updater     *Updater
}

func ACMoveTo(node INode, dest Vec3, NeedTime float64, EndCallFunc func(INode)) {
	mt := new(moveToS)
	mt.node = node
	mt.NeedTime = NeedTime
	mt.curtime = 0
	mt.MoveEndFunc = EndCallFunc
	NPV := node.GetTransfrom().GetPositionV()
	SubV := dest.Sub(&NPV)
	SubV = SubV.Div1(NeedTime)
	mt.Dis = SubV
	mt.Dest = &dest
	mt.Updater = ACTimeUpdate.AddUpdater(_update_MoveTo, mt, 0)
}

func _update_MoveTo(dt float64, This interface{}) {
	mt := This.(*moveToS)
	mt.curtime += dt
	if mt.curtime >= mt.NeedTime {
		mt.node.GetTransfrom().SetPositionV(*mt.Dest)
		mt.Updater.Del()
		if mt.MoveEndFunc != nil {
			mt.MoveEndFunc(mt.node)
		}
	}
	oldV := mt.node.GetTransfrom().GetPositionV()
	AddV := mt.Dis.Scaled(dt)
	oldV.Add(AddV)
	mt.node.GetTransfrom().SetPositionV(oldV)
}
